package com.spzx.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.domain.SkuLockVo;
import com.spzx.product.domain.Product;
import com.spzx.product.domain.ProductDetails;
import com.spzx.product.domain.ProductSku;
import com.spzx.product.domain.SkuStock;
import com.spzx.product.mapper.ProductDetailsMapper;
import com.spzx.product.mapper.ProductMapper;
import com.spzx.product.mapper.ProductSkuMapper;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2024-11-12
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {
    @Autowired
    private ProductSkuMapper productSkuMapper;

    @Autowired
    private ProductDetailsMapper productDetailsMapper;

    @Autowired
    private SkuStockMapper skuStockMapper;

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public List<Product> selectProductList() {
        return baseMapper.selectProductList();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertProduct(Product product) {
        baseMapper.insert(product);
        List<ProductSku> productSkuList = product.getProductSkuList();
        for (int i = 0; i < productSkuList.size(); i++) {
            //添加中间表
            ProductSku productSku = productSkuList.get(i);
            productSku.setProductId(product.getId());
            productSku.setSkuCode(product.getId()+"_"+i);
            productSku.setSkuName(product.getName()+" "+productSku.getSkuSpec());
            productSku.setStatus(0);
            productSkuMapper.insert(productSku);
            //添加库存信息SkuStock
            SkuStock skuStock = new SkuStock();
            skuStock.setSkuId(productSku.getId());
            skuStock.setTotalNum(productSku.getStockNum());
            skuStock.setLockNum(0);
            skuStock.setAvailableNum(productSku.getStockNum());
            skuStock.setSaleNum(0);
            skuStockMapper.insert(skuStock);
        }
        //添加商品详情
        ProductDetails productDetails = new ProductDetails();
        productDetails.setProductId(product.getId());
        productDetails.setImageUrls(String.join("，",product.getDetailsImageUrlList()));
        productDetailsMapper.insert(productDetails);
        return 1;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateStatus(Long id, Integer status) {
        if (status != 1 && status != -1) {
            throw new ServiceException("非法值");
        }

        //Product product = baseMapper.selectById(id);//多一次查询，效率低
        Product product = new Product();
        product.setId(id);
        product.setStatus(status);
        baseMapper.updateById(product);

        productSkuMapper.update(null,new LambdaUpdateWrapper<ProductSku>()
                .eq(ProductSku::getProductId,id)
                .set(ProductSku::getStatus,status));

        String key = "product:sku:data";
        List<ProductSku> productSkuList = productSkuMapper.selectList(new LambdaQueryWrapper<ProductSku>()
                .eq(ProductSku::getProductId, id));
        // bitmap防止缓存穿透
        if (status == 1){
            // 商品上架时，将 sku ID 列表放入 bitmap
            productSkuList.forEach(item ->{
                redisTemplate.opsForValue().setBit(key,item.getId(),false);
            });
        }

    }

    @Override
    public int deleteProductByIds(List<Long> ids) {
        //删除商品信息
        baseMapper.deleteBatchIds(ids);
        //根据id列表获取中间表ProductSku集合
        List<ProductSku> productSkuList = productSkuMapper.selectList(new LambdaQueryWrapper<ProductSku>()
                .in(ProductSku::getProductId, ids)
                .select(ProductSku::getId));//指定返回字段，只返回id。提高效率
        //根据商品id获取库存信息id列表
        List<Long> skuIdList = productSkuList.stream().map(ProductSku::getId).collect(Collectors.toList());
        //根据ProductSku id删除
        productSkuMapper.delete(new LambdaQueryWrapper<ProductSku>()
                .in(ProductSku::getProductId, ids));
        //根据库存信息id删除库存信息
        skuStockMapper.delete(
                new LambdaQueryWrapper<SkuStock>()
                        .in(SkuStock::getSkuId, skuIdList)
        );
        //根据商品id删除商品详情信息
        productDetailsMapper.delete(
                new LambdaQueryWrapper<ProductDetails>()
                        .in(ProductDetails::getProductId, ids));
        return 1;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void minus(String orderNo) {
        //幂等性处理
        String key = "sku:minus:" + orderNo;
        //业务去重，防止重复消费
        Boolean isExist = redisTemplate.opsForValue().setIfAbsent(key, orderNo, 1, TimeUnit.HOURS);
        if (!isExist)return;
        //获取锁定库存的缓存信息
        String dataKey = "sku:lock:data:" + orderNo;
        List<SkuLockVo> skuLockVoList= (List<SkuLockVo>) redisTemplate.opsForValue().get(dataKey);
        if (CollectionUtils.isEmpty(skuLockVoList)){
            return;
        }

        //减库存
        skuLockVoList.forEach(skuLockVo -> {
            int row = skuStockMapper.minus(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
        });

        // 扣减库存之后，删除锁定库存的缓存。
        this.redisTemplate.delete(dataKey);
    }


}
